package oboe.core;


import haxe.rtti.Meta;
import oboe.controllers.Translator;

enum SignalDirection
{
	SIG_UP;
	SIG_DOWN;
	SIG_ANY;
}

class SigSlotCollection extends Unique
{
	private var children:Hash<SigSlotCollection>;
	private var translators:Hash<Translator>;

	private var slotRegistry:Hash< Hash<SigSlot> >;

	public function new()
	{
		super();
		this.children = new Hash();
		this.translators = null;
	}

	
	public function addChild( ichild:ISigSlot ):Void
	{
		if ( ichild == null ) return;
		var child:SigSlot = Reflect.field(ichild, "sigslot");
		if ( child == this ) return;
		
		if( this.slotRegistry == null )
		{
			this.slotRegistry = new Hash< Hash< SigSlot > >();
		}
		
		if ( Std.is( child, Translator ) )
		{
			if ( this.translators == null ) this.translators = new Hash<Translator>();
			this.translators.set( child.uniqueId, cast child );
		}
		
		for( slotName in child.slots() )
		{
			var slotList:Hash< SigSlot > = this.slotRegistry.get( slotName );
			if( slotList == null )
			{
				slotList = new Hash< SigSlot >();
				this.slotRegistry.set( slotName, slotList );
			}
			slotList.set( child.uniqueId, child );
		}
		
		this.children.set( child.uniqueId, child );
	}
	

	public function removeChild( ichild:ISigSlot ):Void
	{
		var child:SigSlot = Reflect.field(ichild, "sigslot");
		if( !this.children.exists( child.uniqueId ) ) return;
		this.children.remove( child.uniqueId );
		if ( Std.is( child, Translator ) && this.translators != null )
		{
			this.translators.remove( child.uniqueId );
		}
		
		for( slotName in child.slots() )
		{
			var slotList:Hash< SigSlot > = this.slotRegistry.get( slotName );
			if( slotList != null )
			{
				slotList.remove( child.uniqueId );
			}
		}
	}

	public function signalDown( name:String, arguments:Array<Dynamic> ):Void
	{
		if( this.slotRegistry != null )
		{
			var listeners:Hash< SigSlot > = this.slotRegistry.get( name );
			if ( listeners != null )
			{
				for( slot in listeners )
				{
					slot._message( name, SignalDirection.SIG_DOWN, arguments );
				}
				if ( this.translators != null )
				{
					for ( listener in this.translators )
					{
						if ( !listeners.exists(listener.uniqueId) )
						{
							listener._message( name, SignalDirection.SIG_DOWN, arguments );
						}
					}
					return;
				}
			}
		}
		if ( this.translators != null )
		{
			for ( listener in this.translators )
			{
				listener._message( name, SignalDirection.SIG_DOWN, arguments );
			}
		}
	}
}